using UnityEngine;
using System.Collections;

public class LevelManager : MonoBehaviour {

	[HideInInspector]
	public static LevelManager instance; // static allows access from anywhere

	private int level;

	private int kONE_CHUNK_LENGTH = 10;
	
	private int E_S_Chunks_Min = 0; // Default settings
	private int E_S_Chunks_Max = 34;
	private int M_S_Chunks_Min = 10;
	private int M_S_Chunks_Max = 51;
	private int H_S_Chunks_Min = 25;
	private int H_S_Chunks_Max = 95;
	private int Ex_S_Chunks_Min = 79;
	private int Ex_S_Chunks_Max = 106;
	
	private int M_D_Chunks_Min = 0; // No dynamic chunks for easy
	private int M_D_Chunks_Max = 15;
	private int H_D_Chunks_Min = 15;
	private int H_D_Chunks_Max = 30;
	private int Ex_D_Chunks_Min = 30;
	private int Ex_D_Chunks_Max = 51;

	private int Easy_Blanks = 22; // Number of blank chunks that will be made
	private int Med_Blanks = 19;
	private int Hard_Blanks = 16;
	private int Ext_Blanks = 13;

	private int Easy_S_Chunks = 1; // Number of static chunks that will be made in a row
	private int Med_S_Chunks = 1;
	private int Hard_S_Chunks = 1;
	private int Ext_S_Chunks = 1;
	
	private int Med_D_Chunks = 1; // Number of dynamic chunks that will be made in a row
	private int Hard_D_Chunks = 1;
	private int Ext_D_Chunks = 1;

	private int Easy_Length = 460; // Length of the level
	private int Med_Length = 580;
	private int Hard_Length = 700;
	private int Ext_Length = 800;

	public GameObject startChunk;
	public GameObject blankChunk;
	public GameObject checkChunk;
	public GameObject[] staticChunks;
	public GameObject[] dynamicChunks;
	public GameObject finishChunk;

	private Quaternion rotation;
	private int i = 0;
	private int onChunk;
	private int chunkTillCheck;

	void Awake()
	{
		instance = this;
	}
	
	void Start () 
	{
		level = DifficultyManager.instance.level;
		BuildLevel ();
	}

	void ResetStuff ()
	{
		i = 0;
		onChunk = 0;
		chunkTillCheck = 0;
	}

	public void NextLevel ()
	{
		level++;

		switch (level) 
		{
		case 0: // Easy
			ResetStuff();
			BuildLevel();
			break;
		case 1: // Med
			ResetStuff();
			BuildLevel();
			break;
		case 2: // Hard
			ResetStuff();
			BuildLevel();
			//InitiateBoss();
			break;
		case 3: // Extreme
			ResetStuff();
			BuildLevel();
			//level = -1; // go back to start, kind of
			break;
		default:
			break;
		}
	}

	void BuildLevel ()
	{
		switch (level) 
		{
		case 0:
			Instantiate(startChunk, new Vector3(0.0f, 0.0f, 25.0f), Quaternion.identity);

			chunkTillCheck = 2;
			onChunk = 1;

			for (i = 6; i < Easy_Length;) // Push i ahead for the inclusion of the start chunk
			{
				for (int b = 0; b < Easy_Blanks; b++) // Create blanks
				{
					Instantiate(blankChunk, new Vector3(0.0f, 0.0f, (i * kONE_CHUNK_LENGTH)), Quaternion.identity);

					i++; // Increase the total 'length'
				}

				if ((onChunk % chunkTillCheck) != 0) 
				{
					for (int sc = 0; sc < Easy_S_Chunks; sc++) // Static Chunk Adder
					{
						int whichChunk = Random.Range(E_S_Chunks_Min, E_S_Chunks_Max); // Range of chunks to use
						int randRot = (int)(Random.Range(0,5));
						int randFlip = (int)(Random.Range(0,2));
						rotation = Quaternion.Euler((180 * randFlip), 0, (90 * randRot)); // Rotate the piece by 90 * randRot
						Instantiate(staticChunks[whichChunk], new Vector3(0.0f, 0.0f, (i * kONE_CHUNK_LENGTH)), rotation); //(180 * randFlip)
						
						i++;
						onChunk++;
					}
				}
				else 
				{
					Instantiate(checkChunk, new Vector3(0.0f, 0.0f, (i * kONE_CHUNK_LENGTH)), Quaternion.identity);

					i++;
					onChunk++;
				}
			}

			Instantiate(finishChunk, new Vector3(0.0f, 0.0f, ((i * kONE_CHUNK_LENGTH) + 25)), Quaternion.identity);
			break;
		case 1:
			Instantiate(startChunk, new Vector3(0.0f, 0.0f, 25.0f), Quaternion.identity);

			chunkTillCheck = 3;
			onChunk = 1;

			for (i = 6; i < Med_Length;) // Push i ahead for the inclusion of the start chunk
			{
				for (int b = 0; b < Med_Blanks; b++) // Create blanks
				{
					Instantiate(blankChunk, new Vector3(0.0f, 0.0f, (i * kONE_CHUNK_LENGTH)), Quaternion.identity);
					
					i++; // Increase the total 'length'
				}

				if ((onChunk % chunkTillCheck) > 1 ) 
				{
					for (int sc = 0; sc < Med_S_Chunks; sc++) // Static Chunk Adder
					{
						int whichChunk = Random.Range(M_S_Chunks_Min, M_S_Chunks_Max); // Range of chunks to use
						int randRot = (int)(Random.Range(0,5));
						int randFlip = (int)(Random.Range(0,2));
						rotation = Quaternion.Euler((180 * randFlip), 0, (90 * randRot)); // Rotate the piece by 90 * randRot
						Instantiate(staticChunks[whichChunk], new Vector3(0.0f, 0.0f, (i * kONE_CHUNK_LENGTH)), rotation); //(180 * randFlip)
						
						i++;
						onChunk++;
					}
				}
				else if ((onChunk % chunkTillCheck) == 1) 
				{
					for (int dc = 0; dc < Med_D_Chunks; dc++) // Dynamic Chunk Adder
					{
						int whichChunk = Random.Range(M_D_Chunks_Min, M_D_Chunks_Max); // Range of chunks to use
						int randRot = (int)(Random.Range(0,5));
						int randFlip = (int)(Random.Range(0,2));
						rotation = Quaternion.Euler((180 * randFlip), 0, (90 * randRot)); // Rotate the piece by 90 * randRot
						Instantiate(dynamicChunks[whichChunk], new Vector3(0.0f, 0.0f, (i * kONE_CHUNK_LENGTH)), rotation); //(180 * randFlip)
						
						i++;
						onChunk++;
					}
				}
				else 
				{
					Instantiate(checkChunk, new Vector3(0.0f, 0.0f, (i * kONE_CHUNK_LENGTH)), Quaternion.identity);
					
					i++;
					onChunk++;
				}
			}
			
			Instantiate(finishChunk, new Vector3(0.0f, 0.0f, ((i * kONE_CHUNK_LENGTH) + 25)), Quaternion.identity);
			break;
		case 2:
			Instantiate(startChunk, new Vector3(0.0f, 0.0f, 25.0f), Quaternion.identity);

			chunkTillCheck = 5;
			onChunk = 1;
			
			for (i = 6; i < Hard_Length;) // Push i ahead for the inclusion of the start chunk
			{
				for (int b = 0; b < Hard_Blanks; b++) // Create blanks
				{
					Instantiate(blankChunk, new Vector3(0.0f, 0.0f, (i * kONE_CHUNK_LENGTH)), Quaternion.identity);
					
					i++; // Increase the total 'length'
				}
				
				if ((onChunk % chunkTillCheck) > 1 ) 
				{
					for (int sc = 0; sc < Hard_S_Chunks; sc++) // Static Chunk Adder
					{
						int whichChunk = Random.Range(H_S_Chunks_Min, H_S_Chunks_Max); // Range of chunks to use
						int randRot = (int)(Random.Range(0,5));
						int randFlip = (int)(Random.Range(0,2));
						rotation = Quaternion.Euler((180 * randFlip), 0, (90 * randRot)); // Rotate the piece by 90 * randRot
						Instantiate(staticChunks[whichChunk], new Vector3(0.0f, 0.0f, (i * kONE_CHUNK_LENGTH)), rotation); //(180 * randFlip)
						
						i++;
						onChunk++;
					}
				}
				else if ((onChunk % chunkTillCheck) == 1) 
				{
					for (int dc = 0; dc < Hard_D_Chunks; dc++) // Dynamic Chunk Adder
					{
						int whichChunk = Random.Range(H_D_Chunks_Min, H_D_Chunks_Max); // Range of chunks to use
						int randRot = (int)(Random.Range(0,5));
						int randFlip = (int)(Random.Range(0,2));
						rotation = Quaternion.Euler((180 * randFlip), 0, (90 * randRot)); // Rotate the piece by 90 * randRot
						Instantiate(dynamicChunks[whichChunk], new Vector3(0.0f, 0.0f, (i * kONE_CHUNK_LENGTH)), rotation); //(180 * randFlip)
						
						i++;
						onChunk++;
					}
				}
				else 
				{
					Instantiate(checkChunk, new Vector3(0.0f, 0.0f, (i * kONE_CHUNK_LENGTH)), Quaternion.identity);
					
					i++;
					onChunk++;
				}
			}
			
			Instantiate(finishChunk, new Vector3(0.0f, 0.0f, ((i * kONE_CHUNK_LENGTH) + 25)), Quaternion.identity);
			break;
		case 3:
			Instantiate(startChunk, new Vector3(0.0f, 0.0f, 25.0f), Quaternion.identity);

			chunkTillCheck = 8;
			onChunk = 1;
			
			for (i = 6; i < Ext_Length;) // Push i ahead for the inclusion of the start chunk
			{
				for (int b = 0; b < Ext_Blanks; b++) // Create blanks
				{
					Instantiate(blankChunk, new Vector3(0.0f, 0.0f, (i * kONE_CHUNK_LENGTH)), Quaternion.identity);
					
					i++; // Increase the total 'length'
				}
				
				if ((onChunk % chunkTillCheck) > 1 ) 
				{
					for (int sc = 0; sc < Ext_S_Chunks; sc++) // Static Chunk Adder
					{
						int whichChunk = Random.Range(Ex_S_Chunks_Min, Ex_S_Chunks_Max); // Range of chunks to use
						int randRot = (int)(Random.Range(0,5));
						int randFlip = (int)(Random.Range(0,2));
						rotation = Quaternion.Euler((180 * randFlip), 0, (90 * randRot)); // Rotate the piece by 90 * randRot
						Instantiate(staticChunks[whichChunk], new Vector3(0.0f, 0.0f, (i * kONE_CHUNK_LENGTH)), rotation); //(180 * randFlip)
						
						i++;
						onChunk++;
					}
				}
				else if ((onChunk % chunkTillCheck) == 1) 
				{
					for (int dc = 0; dc < Ext_D_Chunks; dc++) // Dynamic Chunk Adder
					{
						int whichChunk = Random.Range(Ex_D_Chunks_Min, Ex_D_Chunks_Max); // Range of chunks to use
						int randRot = (int)(Random.Range(0,5));
						int randFlip = (int)(Random.Range(0,2));
						rotation = Quaternion.Euler((180 * randFlip), 0, (90 * randRot)); // Rotate the piece by 90 * randRot
						Instantiate(dynamicChunks[whichChunk], new Vector3(0.0f, 0.0f, (i * kONE_CHUNK_LENGTH)), rotation); //(180 * randFlip)
						
						i++;
						onChunk++;
					}
				}
				else 
				{
					Instantiate(checkChunk, new Vector3(0.0f, 0.0f, (i * kONE_CHUNK_LENGTH)), Quaternion.identity);
					
					i++;
					onChunk++;
				}
			}
			
			Instantiate(finishChunk, new Vector3(0.0f, 0.0f, ((i * kONE_CHUNK_LENGTH) + 25)), Quaternion.identity);
			break;
		default:
			break;
		}
	}
}